package com.epoint.java8;

import org.junit.Test;

import java.util.Comparator;
import java.util.function.*;

/**
 * 方法引用
 * 本质还是lambda表达式，只是属于特殊的一种
 *
 * 使用格式
 *      1.对象::非静态方法
 *      2.类::静态方法
 *      3.类::非静态方法
 */
public class MethodRefDemo {

    /**
     * 情景一：对象：：实例方法
     * Consumer中的void accept(T t)
     *
     * PrintStream中的void println(T t)
     */
    @Test
    public void test1(){
        consumerTest(500D, new Consumer<Double>() {
            @Override
            public void accept(Double aDouble) {
                System.out.println(aDouble);
            }
        });

        System.out.println("------------------------------------------");

        consumerTest(600D, money -> System.out.println(money));

        System.out.println("-------------------------------------------");

        /**
         * 分析：System.out是一个对象，他有一个方法是println而这个方法和接口的所有的形参和返回值一摸一样，则可以使用
         * 即 System.out的println <==> Consumer.accept
         */
        consumerTest(700D, System.out :: println);
    }

    public void consumerTest(Double money, Consumer<Double> consumer){
        consumer.accept(money);
    }

    /**
     * 情况二：类::静态方法
     * Comparator中的int compare(T t1, T t2)
     * Integer中的int compare(T t1, T t2)
     */
    @Test
    public void test2(){
        Comparator<Integer> compare = Integer::compare;
        System.out.println(compare.compare(1, 2));

        System.out.println(Integer.compare(1, 2));

        /**
         * 此时的 compare.compare(1, 2) ==> Integer.compare(1,2)
         */


        /**********************************************/
        Function<Double, Long> doubleConsumer = Math::round;
        System.out.println(doubleConsumer.apply(50.0));
    }

    /**
     * 情况三：类::实例方法
     * Comparator中的int compare(T t1, T t2)
     * 我自己找到一个 String的indexOf(String str)
     *
     * 当形参个数不一致的时候，也支持把第一个形参作为当前类的对象，然后把第一个参数后面的参数和 接口的形参进行对比，
     *
     * 比如 Comparator的compare有2个参数，而String的indexOf只有一个
     * 那么compare的第一个参数被作为 indexOf的对象
     * 也就是：   compare(a, b) ==> a.indexOf(b)
     *
     * 诀窍：将lambda或者方法引用 的部分 直接作为 接口的唯一的抽象方法的方法体 去看待就很顺利了
     *
     */
    @Test
    public void test3(){
        Comparator<String> stringComparator = String::indexOf;
        int compare = stringComparator.compare("123", "2");
        System.out.println(compare);
    }
}
